package com.nuc.bigdata.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nuc.bigdata.exception.BusinessException;
import com.nuc.bigdata.model.ResultCode;
import com.nuc.bigdata.orm.dto.PhotoNewsDto;
import com.nuc.bigdata.orm.entity.PhotoNews;
import com.nuc.bigdata.orm.entity.PhotoNewsCategory;
import com.nuc.bigdata.orm.entity.PhotoNewsClicks;
import com.nuc.bigdata.orm.entity.PhotoNewsPicture;
import com.nuc.bigdata.orm.feign.PhotoNewsFeign;
import com.nuc.bigdata.orm.feign.PhotoNewsPictureFeign;
import com.nuc.bigdata.orm.mapper.PhotoNewsCategoryMapper;
import com.nuc.bigdata.orm.mapper.PhotoNewsClicksMapper;
import com.nuc.bigdata.orm.mapper.PhotoNewsMapper;
import com.nuc.bigdata.orm.mapper.PhotoNewsPictureMapper;
import com.nuc.bigdata.service.PhotoNewsService;
import org.bouncycastle.asn1.pkcs.Pfx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;

/**
 * @author JackLuo
 * @date 2019/11/26
 */
@Service
public class PhotoNewsServiceImpl implements PhotoNewsService {

    private final PhotoNewsMapper photoNewsMapper;
    private final PhotoNewsClicksMapper photoNewsClicksMapper;
    private final PhotoNewsPictureMapper pictureMapper;
    private final PhotoNewsCategoryMapper categoryMapper;

    @Autowired
    PhotoNewsServiceImpl(PhotoNewsMapper photoNewsMapper,
                         PhotoNewsClicksMapper photoNewsClicksMapper,
                         PhotoNewsPictureMapper pictureMapper,
                         PhotoNewsCategoryMapper categoryMapper) {
        this.photoNewsMapper = photoNewsMapper;
        this.photoNewsClicksMapper = photoNewsClicksMapper;
        this.pictureMapper = pictureMapper;
        this.categoryMapper = categoryMapper;
    }

    /**
     * 通过菜单类别获取图片资讯Feign
     *
     * @param menuId 菜单唯一标识
     * @return 图片资讯Feign的ArrayList
     */
    @Override
    public ArrayList<PhotoNewsFeign> listByMenuId(String menuId) {
        ArrayList<PhotoNewsFeign> photoNewsFeigns = new ArrayList<>();
        ArrayList<PhotoNews> photoNews;
        if ("all".equals(menuId) || StringUtils.isEmpty(menuId)) {
            photoNews = photoNewsMapper.listNewsAll();
        } else {
            photoNews = photoNewsMapper.listNewsByMenuId(menuId);
        }

        if (0 != photoNews.size()) {
            for (PhotoNews news : photoNews) {
                PhotoNewsFeign photoNewsFeign = transformPhotoNews(news);
                photoNewsFeigns.add(photoNewsFeign);
            }
        }
        return photoNewsFeigns;
    }

    /**
     * 通过图片资讯id获取图片资讯feign
     *
     * @param pnId 资讯唯一标识
     * @return 图片资讯feign
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public PhotoNewsFeign queryByPnId(String pnId) {
        PhotoNews photoNews = photoNewsMapper.selectByPnId(pnId);
        PhotoNewsClicks photoNewsClicks = new PhotoNewsClicks();
        PhotoNewsClicks newsClicks = photoNewsClicksMapper.selectByPnId(pnId);
        if (ObjectUtils.isEmpty(newsClicks)) {
            photoNewsClicks.setPnId(pnId);
            photoNewsClicks.setClick(1L);
            photoNewsClicksMapper.insert(photoNewsClicks);
        } else {
            Long click = newsClicks.getClick();
            newsClicks.setClick(click + 1);
            QueryWrapper<PhotoNewsClicks> qy = new QueryWrapper<>();
            qy.eq("pn_id", pnId);
            photoNewsClicksMapper.update(newsClicks, qy);
        }

        return transformPhotoNews(photoNews);
    }

    /**
     * 创建图片文章
     *
     * @param newsDto 图片资讯dto
     * @param userId  用户唯一标识
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public void createPhotoNews(PhotoNewsDto newsDto, String userId) {
        String pnId = IdUtil.fastSimpleUUID();
        // 实例化新闻对象
        PhotoNews photoNews = buildPhotoNews(pnId, newsDto.getPnTitle(), newsDto.getPnNews(), userId);
        photoNewsMapper.insert(photoNews);
        // 实例化归属菜单项
        PhotoNewsCategory photoNewsCategory = buildNewsCategory(pnId, newsDto.getMenuId(), userId);
        categoryMapper.insert(photoNewsCategory);
        // 实例化新闻图片对象
        ArrayList<String> pictureIds = newsDto.getPictureIds();
        pictureIds.forEach(id -> {
            PhotoNewsPicture photoNewsPicture = buildPhotoNewsPicture(pnId, id, userId);
            pictureMapper.insert(photoNewsPicture);
        });
    }

    /**
     * 修改图片文章
     *
     * @param pnId    文章唯一标识
     * @param newsDto 图片资讯dto
     * @param userId  用户唯一标识
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public void updatePhotoNews(String pnId, PhotoNewsDto newsDto, String userId) {
        // 拿到文章对应的信息
        PhotoNews photoNews = photoNewsMapper.selectByPnId(pnId);
        PhotoNewsCategory photoNewsCategory = categoryMapper.selectByPnId(pnId);
        ArrayList<PhotoNewsPicture> photoNewsPictures = pictureMapper.listAllNewsPicture(pnId);
        // 修改文章
        if (ObjectUtils.isEmpty(photoNews)) {
            throw new BusinessException(ResultCode.PHOTO_NEWS_NOT_EXIST,null);
        }else  {
            // 更新图片资讯
            PhotoNews news = updateBuildPhotoNews(photoNews, newsDto.getPnTitle(), newsDto.getPnNews(), userId);
            UpdateWrapper<PhotoNews> photoNewsUq = new UpdateWrapper<>();
            photoNewsUq.eq("pn_id",pnId);
            photoNewsMapper.update(news,photoNewsUq);
            // 更新资讯分类信息
            PhotoNewsCategory newsCategory = updateBuildNewsCategory(photoNewsCategory, newsDto.getMenuId(), userId);
            UpdateWrapper<PhotoNewsCategory> photoNewsCategoryUq = new UpdateWrapper<>();
            photoNewsCategoryUq.eq("pn_id",pnId);
            categoryMapper.update(newsCategory,photoNewsCategoryUq);
            // 更新资讯图片信息(实际上不会更改某一项图片信息，只会增加或删除某一条记录)
            ArrayList<String> newPictureIds = newsDto.getPictureIds();
            ArrayList<String> oldPictureIds = new ArrayList<>();
            photoNewsPictures.forEach(item -> oldPictureIds.add(item.getPictureId()));
            // 以新的图片列表为准，更新图片信息
            // 1. 未修改的图片，就不变；新列表中去掉的就删除；增加的就新插入
            oldPictureIds.forEach(id -> {
                // 如果新的图片列表中不包含旧的中这一项就删除
                // 如果包含，就在新列表中移除；最后新列表保留的就是需要新插入的图片
                if (!newPictureIds.contains(id)) {
                    pictureMapper.deleteNewsPicture(pnId,id);
                }else {
                    newPictureIds.remove(id);
                }
            });
            // 2.插入新列表中的新图片
            newPictureIds.forEach(id -> {
                PhotoNewsPicture newsPicture = buildPhotoNewsPicture(pnId, id, userId);
                pictureMapper.insert(newsPicture);
            });
        }
    }

    /**
     * 删除图片文章
     *
     * @param pnId 文章唯一标识
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public void removePhotoNews(String pnId) {
        // 拿到文章对应的信息
        PhotoNews photoNews = photoNewsMapper.selectByPnId(pnId);
        PhotoNewsCategory photoNewsCategory = categoryMapper.selectByPnId(pnId);
        ArrayList<PhotoNewsPicture> photoNewsPictures = pictureMapper.listAllNewsPicture(pnId);
        if (ObjectUtils.isEmpty(photoNews)) {
            throw new BusinessException(ResultCode.PHOTO_NEWS_NOT_EXIST,null);
        } else {
            // 删除资讯
            photoNewsMapper.deleteByPnId(pnId);
            if (!ObjectUtils.isEmpty(photoNewsCategory)) {
                categoryMapper.deleteByPnId(pnId);
            }
            if (!CollectionUtils.isEmpty(photoNewsPictures)) {
                pictureMapper.deleteByPnId(pnId);
            }
        }
    }


    /**
     * 更新构建图片资讯分类信息
     * @param newsCategory 资讯所属分类实体
     * @param menuId 菜单项唯一标识
     * @param userId 用户唯一标识
     * @return 资讯分类实体
     */
    private PhotoNewsCategory updateBuildNewsCategory(PhotoNewsCategory newsCategory, String menuId, String userId) {
        newsCategory.setMenuId(menuId);
        newsCategory.setUpdateTime(new Date());
        newsCategory.setLastUpdatedBy(userId);
        return newsCategory;
    }

    /**
     * 更新构建图片资讯信息
     * @param photoNews 图片资讯实体
     * @param pnTitle 资讯标题
     * @param pnNews  资讯内容
     * @param userId  用户唯一标识
     * @return 图片资讯实体
     */
    private PhotoNews updateBuildPhotoNews(PhotoNews photoNews, String pnTitle, String pnNews, String userId) {
        photoNews.setPnTitle(pnTitle);
        photoNews.setPnNews(pnNews);
        photoNews.setUpdateTime(new Date());
        photoNews.setLastUpdatedBy(userId);
        return photoNews;
    }

    /**
     * 构造一个图片资讯实体
     *
     * @param pnId    资讯唯一标识
     * @param pnTitle 资讯标题
     * @param pnNews  资讯内容
     * @param userId  用户唯一标识
     * @return 图片资讯实体
     */
    private PhotoNews buildPhotoNews(String pnId, String pnTitle, String pnNews, String userId) {
        PhotoNews photoNews = new PhotoNews();
        photoNews.setPnId(pnId);
        photoNews.setPnTitle(pnTitle);
        photoNews.setPnNews(pnNews);
        photoNews.setCreatedBy(userId);
        return photoNews;
    }

    /**
     * 构造一个图片资讯图片实体
     *
     * @param pnId      资讯唯一标识
     * @param pictureId 图片唯一标识
     * @param userId    用户唯一标识
     * @return 图片资讯图片实体
     */
    private PhotoNewsPicture buildPhotoNewsPicture(String pnId, String pictureId, String userId) {
        PhotoNewsPicture photoNewsPicture = new PhotoNewsPicture();
        photoNewsPicture.setPnId(pnId);
        photoNewsPicture.setPictureId(pictureId);
        photoNewsPicture.setCreatedBy(userId);
        return photoNewsPicture;
    }

    /**
     * 构造一个图片分类实体(保存分类信息)
     *
     * @param pnId   资讯唯一标识
     * @param menuId 菜单唯一标识
     * @param userId 用户唯一标识
     * @return 分类实体
     */
    private PhotoNewsCategory buildNewsCategory(String pnId, String menuId, String userId) {
        PhotoNewsCategory newsCategory = new PhotoNewsCategory();
        newsCategory.setCreatedBy(userId);
        newsCategory.setPnId(pnId);
        newsCategory.setMenuId(menuId);
        return newsCategory;
    }

    /**
     * 提取图片资讯对象中想要传输给front的信息
     *
     * @param photoNews
     * @return
     */
    private PhotoNewsFeign transformPhotoNews(PhotoNews photoNews) {
        PhotoNewsFeign photoNewsFeign = new PhotoNewsFeign();
        ArrayList<PhotoNewsPictureFeign> pictureFeignArrayList = new ArrayList<>();
        PhotoNewsClicks newsClicks = photoNews.getClick();
        ArrayList<PhotoNewsPicture> pictureList = photoNews.getPictureList();

        for (PhotoNewsPicture newsPicture : pictureList) {
            PhotoNewsPictureFeign pictureFeign = transformPhotoPicture(newsPicture);
            pictureFeignArrayList.add(pictureFeign);
        }

        if (ObjectUtils.isEmpty(newsClicks)) {
            photoNewsFeign.setClickNumber(0L);
        } else {
            photoNewsFeign.setClickNumber(newsClicks.getClick());
        }

        photoNewsFeign.setPnId(photoNews.getPnId());
        photoNewsFeign.setPnNews(photoNews.getPnNews());
        photoNewsFeign.setPnTitle(photoNews.getPnTitle());
        photoNewsFeign.setUserId(photoNews.getCreatedBy());
        photoNewsFeign.setCreteTime(photoNews.getCreateTime());
        photoNewsFeign.setId(photoNews.getId());
        photoNewsFeign.setPictureList(pictureFeignArrayList);

        return photoNewsFeign;
    }

    /**
     * 提取图片对象中想要传输给front的信息
     *
     * @param photoNewsPicture
     * @return
     */
    private PhotoNewsPictureFeign transformPhotoPicture(PhotoNewsPicture photoNewsPicture) {
        PhotoNewsPictureFeign pictureFeign = new PhotoNewsPictureFeign();
        pictureFeign.setPnId(photoNewsPicture.getPnId());
        pictureFeign.setPictureId(photoNewsPicture.getPictureId());
        pictureFeign.setId(photoNewsPicture.getId());
        return pictureFeign;
    }
}
